﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BusinessPlatform.Core.BusinessObject.Properties;
using BusinessPlatform.Core.Criteria;
using System.Data.Common;
using BusinessPlatform.Core.Database;

namespace BusinessPlatform.Core.EntityParser
{
    internal enum DataPortalType
    {
        SELECT,
        INSERT,
        DELETE,
        UPDATE
    }
    internal class DataPortal : IDataPortal
    {
        #region private variable
        private IPropertiesManager _Properties;
        private IDatabase _db;
        private ICriteria _cri;

        private DataPortalType _QueryType;
        #endregion
        #region constractor
        internal DataPortal()
        {

        }
        internal DataPortal(IPropertiesManager Properties)
        {
            _Properties = Properties;
        }
        internal DataPortal(IDatabase db, IPropertiesManager Properties, DataPortalType QueryType)
        {
            _db = db;
            _Properties = Properties;
            _QueryType = QueryType;
        }
        internal DataPortal(IDatabase db, IPropertiesManager Properties, ICriteria Cri)
        {
            _db = db;
            _Properties = Properties;
            _cri = Cri;
            _QueryType = DataPortalType.SELECT;
        }
        #endregion
        #region private methods
        /// <summary>
        /// 把字段列表拼接到一起
        /// </summary>
        /// <param name="tableInfo"></param>
        /// <returns></returns>
        private string GetFieldList(ITableInfo tableInfo)
        {
            string FieldString = string.Empty;
            foreach (var fieldInfo in tableInfo.Fileds)
            {
                FieldString += ",[" + fieldInfo.Name + "]";
            }
            return FieldString.Substring(1);
        }
        #region T-SQL
        /// <summary>
        /// 获取SELECT T-SQL语句
        /// </summary>
        /// <param name="QueryType"></param>
        /// <returns></returns>
        private string GetSelectString(ICriteria cri)
        {
            //查询语句
            string QueryString = string.Empty;
            //条件
            string WhereString = string.Empty;
            //操作符
            string OperationSymbol = string.Empty;
            int n = 1;
            QueryString = "SELECT {0} FROM [{1}] {2}";
            if (cri != null)
            {
                WhereString = "Where ";
                foreach (var con in cri.Conditions)
                {
                    OperationSymbol = GetOperationFlag(con.Operation, con.FieldName);
                    #region 左括号
                    for (int i = 1; i <= con.BracketOpenNum; i++)
                    {
                        WhereString += "(";
                    }
                    #endregion
                    WhereString += con.FieldName + OperationSymbol;
                    if (n != cri.Conditions.Count)
                        WhereString += " " + con.Relationship + " ";
                    #region 右括号
                    for (int i = 1; i <= con.BracketCloseNum; i++)
                    {
                        WhereString += ")";
                    }
                    #endregion
                    n++;
                }
            }
            QueryString = string.Format(QueryString, GetFieldList(_Properties.TableInfo), _Properties.TableInfo.TableName, WhereString);
            return QueryString;
        }
        /// <summary>
        /// 获取操作标志对应的SQL符号
        /// </summary>
        /// <param name="OperationSymbol"></param>
        /// <returns></returns>
        private string GetOperationFlag(EnumOperateSymbol OperationSymbol, string FieldName)
        {
            string OperationFlag = string.Empty;
            switch (OperationSymbol)
            {
                /// <summary>
                /// =
                /// Equal
                /// </summary>
                case EnumOperateSymbol.EQUAL:
                    OperationFlag = " = " + "@" + FieldName;
                    break;
                /// <summary>
                /// >
                /// Greater than
                /// </summary>
                case EnumOperateSymbol.GRATER_THAN:
                    OperationFlag = " > " + "@" + FieldName;
                    break;
                /// <summary>
                /// <
                /// Less then
                /// </summary>
                case EnumOperateSymbol.LESS_THAN:
                    OperationFlag = " < " + "@" + FieldName;
                    break;
                /// <summary>
                /// >=
                /// Greater or Equal
                /// </summary>
                case EnumOperateSymbol.GRATER_EQUAL:
                    OperationFlag = " >= " + "@" + FieldName;
                    break;
                /// <summary>
                /// <=
                /// Less or equal
                /// </summary>
                case EnumOperateSymbol.LESS_EQUAL:
                    OperationFlag = " <= " + "@" + FieldName;
                    break;
                /// <summary>
                /// <>
                /// Not equal
                /// </summary>
                case EnumOperateSymbol.NOT_EQUAL:
                    OperationFlag = " <> " + "@" + FieldName;
                    break;
                /// <summary>
                /// Like (%……%)
                /// </summary>
                case EnumOperateSymbol.CONTAIN:
                    OperationFlag = " Like %" + "@" + FieldName + "%";
                    break;
                /// <summary>
                /// Not like (%……%)
                /// </summary>
                case EnumOperateSymbol.NOT_CONTAIN:
                    OperationFlag = " Not like %" + "@" + FieldName + "%";
                    break;
                /// <summary>
                /// Like(……%)
                /// </summary>
                case EnumOperateSymbol.CONTAIN_START:
                    OperationFlag = " Like " + "@" + FieldName + "%";
                    break;
                /// <summary>
                /// Not like(……%)
                /// </summary>
                case EnumOperateSymbol.NOT_CONTAIN_START:
                    OperationFlag = " Not like " + "@" + FieldName + "%";
                    break;
                /// <summary>
                /// Like (%……)
                /// </summary>
                case EnumOperateSymbol.CONTAIN_END:
                    OperationFlag = " Like %" + "@" + FieldName;
                    break;
                /// <summary>
                /// Not like (%……)
                /// </summary>
                case EnumOperateSymbol.NOT_CONTAIN_END:
                    OperationFlag = " Not like %" + "@" + FieldName;
                    break;
                // 11 Between (A1...An) 
                case EnumOperateSymbol.BETWEEN:
                    OperationFlag = " Between (" + "@" + FieldName + ",@" + FieldName + ")";
                    break;
                // 12 Not between (A1...An) 
                case EnumOperateSymbol.NOT_BETWEEN:
                    OperationFlag = " Not between (" + "@" + FieldName + ",@" + FieldName + ")";
                    break;
                /// <summary>
                /// Is null
                /// </summary>
                case EnumOperateSymbol.IS_NULL:
                    OperationFlag = " Is null";
                    break;// 13 Empty 
                /// <summary>
                /// Not is null
                /// </summary>
                case EnumOperateSymbol.NOT_NULL:
                    OperationFlag = " Not is null";
                    break;
            }
            return OperationFlag;
        }
        /// <summary>
        /// 获取INSERT T-SQL语句
        /// </summary>
        /// <returns></returns>
        private string GetInsertString()
        {
            string QueryString = string.Empty;
            string ParameterString = string.Empty;
            QueryString = "INSERT INTO {0} ({1}) VALUES ({2})";
            #region 拼接插入语句
            foreach (var fieldInfo in _Properties.TableInfo.Fileds)
            {
                ParameterString += ",@" + fieldInfo.Name;
            }
            QueryString = string.Format(QueryString, _Properties.TableInfo.TableName, GetFieldList(_Properties.TableInfo), ParameterString.Substring(1));
            #endregion
            return QueryString;
        }
        /// <summary>
        /// 删除语句的字符串
        /// </summary>
        /// <returns></returns>
        private string GetDeleteString()
        {
            string QueryString = string.Empty;
            string ParameterString = string.Empty;
            QueryString = "DELETE FROM {0} Where {1}";
            var PropertyInfo = _Properties.GetPrimaryPropertyInfo();
            ParameterString = PropertyInfo.Name + " = @" + PropertyInfo.Name;
            foreach (var item in _Properties.GetUnionPropertyInfo())
            {
                PropertyInfo = item;
                ParameterString += " And " + PropertyInfo.Name + " = @" + PropertyInfo.Name;

            }
            QueryString = string.Format(QueryString, _Properties.TableInfo.TableName, ParameterString);
            return QueryString;
        }
        #endregion
        #region DbParameters
        /// <summary>
        /// 获取数据参数
        /// </summary>
        /// <param name="db"></param>
        /// <param name="ParameterName"></param>
        /// <param name="DbType"></param>
        /// <param name="Value"></param>
        /// <returns></returns>
        private DbParameter GetDbParameter(IDatabase db, string ParameterName, Type DbType, object Value)
        {
            return db.AddParameter(ParameterName, Common.ConvertEx.ToDbType(DbType), Value);
        }

        private IList<DbParameter> GetInsertDbParameters()
        {
            var Pars = new List<DbParameter>();
            foreach (var Par in _Properties.TableInfo.Fileds)
            {
                Pars.Add(GetDbParameter(_db, Par.Name, Par.DbType, Par.PropertyValue));
            }
            return Pars;
        }
        private IList<DbParameter> GetSelectDbParameters()
        {
            var dbParameters = new List<DbParameter>();
            if (_cri != null)
            {
                foreach (var con in _cri.Conditions)
                {
                    var PropertyInfo = _Properties.GetPropertyInfoByFieldName(con.FieldName);
                    dbParameters.Add(GetDbParameter(_db, PropertyInfo.Name, PropertyInfo.DbType, con.ConditionValue));
                }
            }
            return dbParameters;
        }
        private IList<DbParameter> GetDeleteDbParameters()
        {
            var dbParameters = new List<DbParameter>();
            var PropertyInfo = _Properties.GetPrimaryPropertyInfo();
            dbParameters.Add(GetDbParameter(_db, PropertyInfo.Name, PropertyInfo.DbType, PropertyInfo.PropertyValue));
            foreach (var item in _Properties.GetUnionPropertyInfo())
            {
                PropertyInfo = item;
                dbParameters.Add(GetDbParameter(_db, PropertyInfo.Name, PropertyInfo.DbType, PropertyInfo.PropertyValue));
            }
            return dbParameters;
        }
        #endregion
        #endregion
        #region public methods
        public string GetQueryString()
        {
            string QueryString = string.Empty;
            switch (_QueryType)
            {
                case DataPortalType.INSERT:
                    QueryString = GetInsertString();
                    break;
                case DataPortalType.DELETE:
                    QueryString = GetDeleteString();
                    break;
                case DataPortalType.SELECT:
                    QueryString = GetSelectString(_cri);
                    break;
            }
            return QueryString;
        }
        public IList<DbParameter> GetDbParameters()
        {
            IList<DbParameter> dbParameters = default(List<DbParameter>);
            switch (_QueryType)
            {
                case DataPortalType.INSERT:
                    dbParameters = GetInsertDbParameters();
                    break;
                case DataPortalType.DELETE:
                    dbParameters = GetDeleteDbParameters();
                    break;
                case DataPortalType.SELECT:
                    dbParameters = GetSelectDbParameters();
                    break;
            }
            return dbParameters;
        }
        #endregion
        /// <summary>
        /// 填充数据到对象实体
        /// </summary>
        /// <param name="DataReader"></param>
        public static void FillData(IPropertiesManager Properties, System.Data.IDataReader DataReader)
        {
            foreach (var field in Properties.TableInfo.Fileds)
            {
                var index = DataReader.GetOrdinal(field.Name);
                object value = DataReader.IsDBNull(index) ? null : DataReader.GetValue(index);
                Properties.SetPropertyValue(field, value);
                //Properties[field.PropertyName].PropertyValue = value;
            }
        }
    }
}
